package com.ruoyi.crm.service.impl;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.enums.AuditStatus;
import com.ruoyi.common.enums.flow.FlowTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.flow.FlowDTO;
import com.ruoyi.common.utils.flow.FlowParamsUtils;
import com.ruoyi.crm.domain.*;
import com.ruoyi.crm.mapper.CrmOrderCollectDetailsMapper;
import com.ruoyi.crm.mapper.CrmOrderPayDetailsMapper;
import com.ruoyi.crm.mapper.CrmProjectMapper;
import com.ruoyi.crm.service.ICrmCustomerService;
import com.ruoyi.crm.service.ICrmOrderRegisterService;
import com.ruoyi.crm.service.ICrmOrderService;
import com.ruoyi.crm.utils.ThreadLocalUtils;
import com.warm.flow.core.dto.FlowParams;
import com.warm.flow.core.enums.SkipType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.crm.mapper.CrmOrderCollectPayMoneyMapper;
import com.ruoyi.crm.service.ICrmOrderCollectPayMoneyService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

/**
 * 收付款管理Service业务层处理
 *
 * @author yanwenliang
 * @date 2024-11-27
 */
@Service
public class CrmOrderCollectPayMoneyServiceImpl extends ServiceImpl<CrmOrderCollectPayMoneyMapper, CrmOrderCollectPayMoney> implements ICrmOrderCollectPayMoneyService
{
    @Autowired
    private CrmOrderCollectPayMoneyMapper crmOrderCollectPayMoneyMapper;

    @Autowired
    private CrmProjectMapper crmProjectMapper;

    @Autowired
    private CrmOrderPayDetailsMapper crmOrderPayDetailsMapper;

    @Autowired
    private CrmOrderCollectDetailsMapper crmOrderCollectDetailsMapper;

    @Autowired
    private ICrmOrderService crmOrderService;

    @Autowired
    private ICrmCustomerService crmCustomerService;
    /**
     * 查询收付款管理
     *
     * @param collectPayMoneyId 收付款管理主键
     * @return 收付款管理
     */
    @Override
    public CrmOrderCollectPayMoney selectCrmOrderCollectPayMoneyByCollectPayMoneyId(String collectPayMoneyId)
    {
        CrmOrderCollectPayMoney collectPayMoney = crmOrderCollectPayMoneyMapper.selectById(collectPayMoneyId);
        //付款明细
        List<CrmOrderPayDetails> crmOrderPayDetails = crmOrderPayDetailsMapper
                .selectList(new LambdaQueryWrapper<CrmOrderPayDetails>()
                        .eq(CrmOrderPayDetails::getCollectPayMoneyId, collectPayMoneyId));
        if(StringUtils.isNotEmpty(crmOrderPayDetails)){
            crmOrderPayDetails.forEach(item->{
                //数据名称转化
                item.setDetailsAmount(item.getPayDetailsAmount());
                item.setDetailsName(item.getPayDetailsName());
            });
            collectPayMoney.setPayDetailsList(crmOrderPayDetails);
        }

        //收款明细
        List<CrmOrderCollectDetails> collectDetailsList = crmOrderCollectDetailsMapper
                .selectList(new LambdaQueryWrapper<CrmOrderCollectDetails>()
                        .eq(CrmOrderCollectDetails::getCollectPayMoneyId, collectPayMoneyId));

        if(StringUtils.isNotEmpty(collectDetailsList)){
            collectPayMoney.setCollectDetailsList(collectDetailsList);
        }

        return collectPayMoney;
    }

    /**
     * 查询收付款管理列表
     *
     * @param crmOrderCollectPayMoney 收付款管理
     * @return 收付款管理
     */
    @Override
    public List<CrmOrderCollectPayMoney> selectCrmOrderCollectPayMoneyList(CrmOrderCollectPayMoney crmOrderCollectPayMoney) {

        if (!SecurityUtils.hasAdmin()){
            crmOrderCollectPayMoney.setUserId(SecurityUtils.getUserId());
        }
        List<CrmOrderCollectPayMoney> crmOrderCollectPayMonies = crmOrderCollectPayMoneyMapper.selectCrmOrderCollectPayMoneyList(crmOrderCollectPayMoney);
        for (CrmOrderCollectPayMoney crmOrderCollectPayMony : crmOrderCollectPayMonies) {
            if (crmOrderCollectPayMony.getMoneyType().equals("1")){
                List<CrmOrderCollectDetails> crmOrderCollectDetails = crmOrderCollectDetailsMapper.selectList(new LambdaQueryWrapper<CrmOrderCollectDetails>()
                        .eq(CrmOrderCollectDetails::getCollectPayMoneyId, crmOrderCollectPayMony.getCollectPayMoneyId()));
                Map<String, BigDecimal> amountMap = crmOrderCollectDetails.stream()
                        .collect(Collectors.groupingBy(
                                CrmOrderCollectDetails::getCollectDetailsStatus,
                                Collectors.reducing(BigDecimal.ZERO, CrmOrderCollectDetails::getCollectDetailsAmount, BigDecimal::add)
                        ));

                BigDecimal noTotalAmount = amountMap.getOrDefault("0", BigDecimal.ZERO);
                BigDecimal totalAmount = amountMap.getOrDefault("1", BigDecimal.ZERO);

                crmOrderCollectPayMony.setNoCollectionCountAmt(noTotalAmount);
                crmOrderCollectPayMony.setCollectionCountAmt(totalAmount);

            } else {
                List<CrmOrderPayDetails> crmOrderPayDetails = crmOrderPayDetailsMapper.selectList(new LambdaQueryWrapper<CrmOrderPayDetails>()
                        .eq(CrmOrderPayDetails::getCollectPayMoneyId, crmOrderCollectPayMony.getCollectPayMoneyId()));

                Map<String, BigDecimal> amountMap = crmOrderPayDetails.stream()
                        .collect(Collectors.groupingBy(
                                CrmOrderPayDetails::getPayDetailsStatus,
                                Collectors.reducing(BigDecimal.ZERO, CrmOrderPayDetails::getPayDetailsAmount, BigDecimal::add)
                        ));

                BigDecimal noTotalAmount = amountMap.getOrDefault("0", BigDecimal.ZERO);
                BigDecimal totalAmount = amountMap.getOrDefault("1", BigDecimal.ZERO);

                crmOrderCollectPayMony.setNoCollectionCountAmt(noTotalAmount);
                crmOrderCollectPayMony.setCollectionCountAmt(totalAmount);
            }
        }
        return crmOrderCollectPayMonies;
    }

    /**
     * 新增收付款管理
     *
     * @param crmOrderCollectPayMoney 收付款管理
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean insertCrmOrderCollectPayMoney(CrmOrderCollectPayMoney crmOrderCollectPayMoney) {
            String idStr = IdWorker.getIdStr();
            crmOrderCollectPayMoney.setCollectPayMoneyId(idStr);
            if(crmOrderCollectPayMoney.getMoneyType().equals("0")){
                //付款逻辑
                List<CrmOrderPayDetails> payDetailsList = crmOrderCollectPayMoney.getPayDetailsList();
                payDetailsList.forEach(item->{
                    item.setUserId(crmOrderCollectPayMoney.getUserId());
                    item.setCollectPayMoneyId(idStr);
                    //数据名称转化
                    item.setPayDetailsAmount(item.getDetailsAmount());
                    item.setPayDetailsName(item.getDetailsName());
                    crmOrderPayDetailsMapper.insert(item);
                });

            }else {
                //收款逻辑
                List<CrmOrderCollectDetails> collectDetailsList = crmOrderCollectPayMoney.getCollectDetailsList();
                collectDetailsList.forEach(item->{
                    item.setUserId(crmOrderCollectPayMoney.getUserId());
                    item.setCollectPayMoneyId(idStr);
                    crmOrderCollectDetailsMapper.insert(item);
                });
            }

         //设置项目id  ProjectId
        if(StringUtils.isNotEmpty(crmOrderCollectPayMoney.getOrderId()) && StringUtils.isEmpty(crmOrderCollectPayMoney.getProjectId())){
            CrmProject crmProject = crmProjectMapper.selectOne(new LambdaQueryWrapper<CrmProject>().eq(CrmProject::getOrderId, crmOrderCollectPayMoney.getOrderId()));
            crmOrderCollectPayMoney.setProjectId(crmProject.getProjectId());
            crmOrderCollectPayMoney.setCustomerId(crmProject.getCustomerId());
        }

        //设置审核状态 待提交
        crmOrderCollectPayMoney.setAuditStatus(AuditStatus.AWAIT_SUBMIT.getCode());
        try {
            ThreadLocalUtils.set(FlowTypeEnum.FLOW_COLLECT_PAY_MONEY.getInfo() + ":" + crmOrderCollectPayMoney.getCollectPayMoneyId(), crmOrderCollectPayMoney);
            //开启工作流
            FlowParamsUtils.start(crmOrderCollectPayMoney, "flow-collectPayMoney", crmOrderCollectPayMoney.getCollectPayMoneyId());
            return this.save(crmOrderCollectPayMoney);
        } finally {
            ThreadLocalUtils.remove(FlowTypeEnum.FLOW_COLLECT_PAY_MONEY.getInfo() + ":" + crmOrderCollectPayMoney.getCollectPayMoneyId());
        }

    }

    /**
     * 修改收付款管理
     *
     * @param crmOrderCollectPayMoney 收付款管理
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateCrmOrderCollectPayMoney(CrmOrderCollectPayMoney crmOrderCollectPayMoney) {
        // 删除原来流程，开启新的流程
        CrmOrderCollectPayMoney collectPayMoney = baseMapper.selectById(crmOrderCollectPayMoney.getCollectPayMoneyId());

        if (ObjectUtils.isEmpty(collectPayMoney)){
            throw new ServiceException("收付款数据不存在，请刷新后重试！");
        }

        //先删除之前付款明细
        crmOrderPayDetailsMapper.delete(new LambdaQueryWrapper<CrmOrderPayDetails>().eq(CrmOrderPayDetails::getCollectPayMoneyId,crmOrderCollectPayMoney.getCollectPayMoneyId()));
        crmOrderCollectDetailsMapper.delete(new LambdaQueryWrapper<CrmOrderCollectDetails>().eq(CrmOrderCollectDetails::getCollectPayMoneyId,crmOrderCollectPayMoney.getCollectPayMoneyId()));
        //保存最新收付款明细
        //付款逻辑
        List<CrmOrderPayDetails> payDetailsList = crmOrderCollectPayMoney.getPayDetailsList();
        payDetailsList.forEach(item->{
            item.setUserId(crmOrderCollectPayMoney.getUserId());
            item.setCollectPayMoneyId(crmOrderCollectPayMoney.getCollectPayMoneyId());
            //数据名称转化
            item.setPayDetailsAmount(item.getDetailsAmount());
            item.setPayDetailsName(item.getDetailsName());
            crmOrderPayDetailsMapper.insert(item);
        });
        //收款逻辑
        List<CrmOrderCollectDetails> collectDetailsList = crmOrderCollectPayMoney.getCollectDetailsList();
        collectDetailsList.forEach(item->{
            item.setUserId(crmOrderCollectPayMoney.getUserId());
            item.setCollectPayMoneyId(crmOrderCollectPayMoney.getCollectPayMoneyId());
            crmOrderCollectDetailsMapper.insert(item);
        });

        try {
            ThreadLocalUtils.set(FlowTypeEnum.FLOW_COLLECT_PAY_MONEY.getInfo() + ":" + crmOrderCollectPayMoney.getCollectPayMoneyId(), crmOrderCollectPayMoney);
            // 如果处于待提交状态，则直接修改
            if (AuditStatus.AWAIT_SUBMIT.getCode().equals(collectPayMoney.getAuditStatus())){

                // 如果新立项状态为提交，则执行流程
                if (AuditStatus.AWAIT_AUDIT.getCode().equals(crmOrderCollectPayMoney.getAuditStatus())) {
                    FlowParamsUtils.submit(crmOrderCollectPayMoney);
                }

                return crmOrderCollectPayMoneyMapper.updateById(crmOrderCollectPayMoney);
            }

            // 如果当前处于待审核也直接修改
            if (AuditStatus.AWAIT_AUDIT.getCode().equals(collectPayMoney.getAuditStatus())){

                // 如果新结算状态为暂存，则删除流程
                if (AuditStatus.AWAIT_SUBMIT.getCode().equals(crmOrderCollectPayMoney.getAuditStatus())) {
                    FlowParamsUtils.remove(collectPayMoney.getInstanceId());
                    // 开启新流程
                    FlowParamsUtils.start(crmOrderCollectPayMoney, "flow-collectPayMoney", collectPayMoney.getCollectPayMoneyId());
                }

                return crmOrderCollectPayMoneyMapper.updateById(crmOrderCollectPayMoney);
            }

            // 在审核中，则删除原来流程
            if (AuditStatus.IN_AUDIT.getCode().equals(collectPayMoney.getAuditStatus())){
                FlowParamsUtils.remove(collectPayMoney.getInstanceId());
            }

            // 开启新流程
            FlowParamsUtils.start(crmOrderCollectPayMoney, "flow-collectPayMoney", crmOrderCollectPayMoney.getCollectPayMoneyId());

            // 如果新立项状态为提交，则执行流程
            if (AuditStatus.AWAIT_AUDIT.getCode().equals(crmOrderCollectPayMoney.getAuditStatus())) {
                FlowParamsUtils.submit(crmOrderCollectPayMoney);
            }

            return crmOrderCollectPayMoneyMapper.updateById(crmOrderCollectPayMoney);
        } finally {
            ThreadLocalUtils.remove(FlowTypeEnum.FLOW_COLLECT_PAY_MONEY.getInfo() + ":" + crmOrderCollectPayMoney.getCollectPayMoneyId());
        }
    }

    /**
     * 批量删除收付款管理
     *
     * @param collectPayMoneyIds 需要删除的收付款管理主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteCrmOrderCollectPayMoneyByCollectPayMoneyIds(String[] collectPayMoneyIds)
    {
        return crmOrderCollectPayMoneyMapper.deleteBatchIds(Arrays.asList(collectPayMoneyIds));
    }

    /**
     * 删除收付款管理信息
     *
     * @param collectPayMoneyId 收付款管理主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteCrmOrderCollectPayMoneyByCollectPayMoneyId(String collectPayMoneyId)
    {
        return crmOrderCollectPayMoneyMapper.deleteById(collectPayMoneyId);
    }



    /**
     * 审核
     *
     * @param crmOrderCollectPayMoney
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int audit(CrmOrderCollectPayMoney crmOrderCollectPayMoney) {
        CrmOrderCollectPayMoney collectPayMoney = baseMapper.selectById(crmOrderCollectPayMoney.getCollectPayMoneyId());

        if (ObjectUtils.isEmpty(collectPayMoney)){
            throw new ServiceException("收付款信息获取失败！，请刷新后重试");
        }

        FlowParamsUtils.skip(crmOrderCollectPayMoney, "");

        return baseMapper.updateById(crmOrderCollectPayMoney);
    }

    /**
     * 提交
     * @param crmOrderCollectPayMoney
     * @return
     */
    @Override
    @Transactional
    public int submit(CrmOrderCollectPayMoney crmOrderCollectPayMoney) {

        CrmOrderCollectPayMoney collectPayMoney = baseMapper.selectById(crmOrderCollectPayMoney.getCollectPayMoneyId());

        if (ObjectUtils.isEmpty(collectPayMoney)){
            throw new ServiceException("费用申请数据不存在，请刷新后重试");
        }

        crmOrderCollectPayMoney.setSkipType(SkipType.PASS.getKey());
        try {
            ThreadLocalUtils.set(FlowTypeEnum.FLOW_COLLECT_PAY_MONEY.getInfo() + ":" + crmOrderCollectPayMoney.getCollectPayMoneyId(), collectPayMoney);
            FlowParams flowParams = FlowParamsUtils.build(crmOrderCollectPayMoney, "");
            FlowParamsUtils.skipByInsId(crmOrderCollectPayMoney, flowParams);
            crmOrderCollectPayMoney.setAuditStatus(AuditStatus.AWAIT_AUDIT.getCode());
            return baseMapper.updateById(crmOrderCollectPayMoney);
        } finally {
            ThreadLocalUtils.remove(FlowTypeEnum.FLOW_COLLECT_PAY_MONEY.getInfo() + ":" + crmOrderCollectPayMoney.getCollectPayMoneyId());
        }

    }

    /**
     * 撤回提交
     * @param crmOrderCollectPayMoney
     * @return
     */
    @Override
    @Transactional
    public int cancelInfo(CrmOrderCollectPayMoney crmOrderCollectPayMoney) {
        CrmOrderCollectPayMoney collectPayMoney = baseMapper.selectById(crmOrderCollectPayMoney.getCollectPayMoneyId());

        if (ObjectUtils.isEmpty(collectPayMoney)){
            throw new ServiceException("费用申请数据不存在，请刷新后重试");
        }

        if (AuditStatus.IN_AUDIT.getCode().equals(collectPayMoney.getAuditStatus())){
            throw new ServiceException("当前费用申请正在审批中，无法撤回");
        }

        FlowParamsUtils.remove(collectPayMoney.getInstanceId());

        FlowParamsUtils.start(crmOrderCollectPayMoney, "flow-collectPayMoney", collectPayMoney.getCollectPayMoneyId());

        crmOrderCollectPayMoney.setAuditStatus(AuditStatus.AWAIT_SUBMIT.getCode());

        return baseMapper.updateById(crmOrderCollectPayMoney);
    }

    /**
     * 通过商机id获取付款详情
     * @param orderId
     * @return
     */
    @Override
    public List<CrmOrderPayDetails> getPayDetailsListByOrderId(String orderId) {
        return baseMapper.getPayDetailsListByOrderId(orderId);
    }

    @Override
    public FlowDTO conversionObj(Serializable id) {
        CrmOrderCollectPayMoney collectPayMoney = baseMapper.getById(id);
        FlowDTO flowDTO = this.buildFlowDTO(collectPayMoney);
        return flowDTO;
    }

    @Override
    public FlowDTO conversionObjByLocal(Serializable id) {
        CrmOrderCollectPayMoney collectPayMoney = ThreadLocalUtils.get(FlowTypeEnum.FLOW_COLLECT_PAY_MONEY.getInfo() + ":" + id);
        CrmOrder crmOrder = crmOrderService.getById(collectPayMoney.getOrderId());
        CrmCustomer customer = crmCustomerService.getById(collectPayMoney.getCustomerId());
        collectPayMoney.setOrderName(crmOrder.getOrderName());
        collectPayMoney.setCustomerName(customer.getCustomerName());
        FlowDTO flowDTO = this.buildFlowDTO(collectPayMoney);
        return flowDTO;
    }

    private FlowDTO buildFlowDTO( CrmOrderCollectPayMoney collectPayMoney ){
        FlowDTO flowDTO = new FlowDTO(collectPayMoney);
        Map<String, Object> businessValue = flowDTO.getBusinessValue();
        businessValue.put("商机名称", collectPayMoney.getOrderName());
        businessValue.put("客户名称", collectPayMoney.getCustomerName());
        businessValue.put("费用类型", "1".equals(collectPayMoney.getMoneyType()) ? "收款" : "付款");
        return flowDTO;
    }
}
